package nirvana.core.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import nirvana.core.domains.ann.AccEntity;
import nirvana.core.domains.entity.DomainBaseEntity;
import nirvana.core.exceptions.BizException;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

/**
 * @author Joseph.Li
 * @author joseph.li@king-v.com
 * Created in 2022-06-19 12:14
 */
public abstract class Repository<MT extends BaseMapper<T>,T> extends ServiceImpl<MT, T> implements IRepository<T> {


    public static final String ID_FIELD = "id";


    public static final String IS_DELETE_FIELD = "is_delete";


    /**
     * 添加
     *
     * @param t
     * @return
     */
    public final boolean create(T t) {
        createToBefore(t);
        if (!save(t)) {
            return Boolean.FALSE;
        }
        createdToAfter(t);

        return Boolean.TRUE;
    }


    /**
     * 创建前
     *
     * @param t
     * @return
     */
    public T createToBefore(T t) {
        return t;
    }

    /**
     * 创建后
     *
     * @param t
     * @return
     */
    public void createdToAfter(T t) {

    }


    /**
     * 编辑
     *
     * @param t
     * @return
     */
    public final boolean edit(T t) {
        editToBefore(t);

        if (!updateById(t)) {
            return Boolean.FALSE;
        }

        editedAfter(t);
        return Boolean.TRUE;
    }


    /**
     * 编辑前
     *
     * @param t
     * @return
     */
    public T editToBefore(T t) {
        return t;
    }


    /**
     * 编辑后
     *
     * @param t
     * @return
     */
    public void editedAfter(T t) {

    }


    /**
     * 当继承了 DomainBaseEntity 类型后，获取时还需要判断 is_delete 字段
     * <p>
     * 应当尝试先从缓存中获取一次，并记录是否成功的从缓存中获取到过
     * <p>
     * 如果在未从缓存中获取，但db中存在数据，则应在缓存中写入
     *
     * @param id
     * @return
     */
    @Override
    public final T getById(Serializable id) {

        T t = getToBefore(id);
        if (t==null){
            t=super.getById(id);
        }
        if (t != null && t instanceof DomainBaseEntity) {
            Boolean isDelete = ((DomainBaseEntity<?>) t).getIsDelete();
            if (isDelete == null || isDelete) {
                t = null;
            }
        }

        getToAfter(t);
        return t;
    }


    /**
     * 根据id获取对象，并检查是否为空
     * @param id
     * @return
     */
    @Override
    public T getByIdCheck(Serializable id) {
        T t = getById(id);
        if (t==null){
            //获取实体名称
            Class<T> entityClass = getEntityClass();
            String entityName="";
            AccEntity annotation = entityClass.getAnnotation(AccEntity.class);
            if (annotation!=null){
                entityName=annotation.value();
            }
            String message = new StringBuilder("未找到该条").append(entityName).append("记录").toString();
            throw new BizException(message);
        }
        return t;
    }

    /**
     * 获取详情的前置操作
     * @param id
     * @return
     */
    public T getToBefore(Serializable id) {
        return null;
    }


    /**
     * 获取详情的后置操作
     * @param t
     */
    public void getToAfter(T t) {
    }


    /**
     * 移除
     *
     * @param id
     * @return
     */
    public final boolean removeById(Serializable id) {

        T t = removeToBefore(id);

        //如果这个类型是软删除，就进行edit操作
        if (t instanceof DomainBaseEntity) {
            ((DomainBaseEntity<?>) t).setIsDelete(Boolean.TRUE);
            return updateById(t);
        } else {
            if (!super.removeById(id)) {
                return Boolean.FALSE;
            }
        }

        removedToAfter(t);

        return Boolean.TRUE;
    }


    /**
     * 删除前置操作
     * @param id
     * @return
     */
    public T removeToBefore(Serializable id) {
        T t = getById(id);
        if (t == null) {
            throw new BizException("删除数据没有找到", new RuntimeException());
        }
        return t;
    }


    /**
     * 删除后置操作
     * @param t
     */
    public void removedToAfter(T t) {

    }


    /**
     * 根据实体类参数获取单条记录
     * @param t
     * @return
     */
    public T getByEntity(T t){
        if (t==null){
            return null;
        }
        if (t instanceof DomainBaseEntity){
            ((DomainBaseEntity<?>) t).setIsDelete(Boolean.FALSE);
        }
        QueryWrapper<T> wrapper = getWrapper(t);
        return getOne(wrapper);
    }


    /**
     * 根据实体类参数获取单条记录
     * @param t
     * @return
     */
    public List<T> getListByEntity(T t){
        if (t==null){
            return null;
        }
        if (t instanceof DomainBaseEntity){
            ((DomainBaseEntity<?>) t).setIsDelete(Boolean.FALSE);
        }
        QueryWrapper<T> wrapper = getWrapper(t);
        if (t instanceof DomainBaseEntity){
           wrapper.orderByAsc("is_disable");
        }
        return list(wrapper);
    }


    /**
     * 根据id列表获取对象列表
     * @param ids
     * @param isDelete
     * @return
     */
    public List<T> getListByIds(List<Long> ids, Boolean isDelete){
        if (CollectionUtils.isEmpty(ids)){
            return Collections.EMPTY_LIST;
        }
        QueryWrapper<T> wrapper = getWrapper();
        wrapper.in("id",ids);
        wrapper.eq(isDelete!=null,"is_delete",isDelete);
        return list(wrapper);
    }

    /**
     *
     * @param ids
     * @return
     */
    public List<T> getListByIds(List<Long> ids){
        return getListByIds(ids,Boolean.FALSE);
    }

    /**
     * 不包含is_delete字段版
     * @param ids
     * @return
     */
    public List<T> getListByIdsNotHasDelete(List<Long> ids){
        return getListByIds(ids,null);
    }






    /**
     * 获取查询包装类
     * 参数为目标类型对象
     *
     * @param t
     * @return
     */
    public QueryWrapper<T> getWrapper(T t) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.setEntity(t);
        return wrapper;
    }


    /**
     * 获取查询包装类
     *
     * @return
     */
    public QueryWrapper<T> getWrapper() {
        return getWrapper(null);
    }


    @Override
    public LambdaQueryWrapper<T> getLambdaWrapper(T t) {

        LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>(t);

        return wrapper;
    }


    @Override
    public LambdaQueryWrapper<T> getLambdaWrapper() {
        return getLambdaWrapper(null);
    }

    public <F> List<T> getListByFieldValueList(SFunction<T, F> field, List<F> valueList) {


        if (CollectionUtils.isEmpty(valueList)){
            return Collections.EMPTY_LIST;
        }
        Class<T> tClass = getEntityClass();
        T t = null;
        try {
            t = tClass.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        if (t instanceof DomainBaseEntity){
            ((DomainBaseEntity<?>) t).setIsDelete(Boolean.FALSE);
        }

        LambdaQueryWrapper<T> wrapper = getLambdaWrapper(t);
        wrapper.in(field, valueList);
        MT mapper = getBaseMapper();

        List<T> list = mapper.selectList(wrapper);

        return list;
    }

}
